import { treeReduceWithoutAfter } from './treeReduce';
import { RESOLVER_NAME } from './formulaResolver';
import ERROR_TYPE from './errorType';
import { calFormulaUnit, UNIT } from './unitCalculate';

const addValidateResult = (accumulator, result) => [...accumulator, result];

const getErrorMessageFromErrorType = errorType => {
    switch (errorType) {
        case ERROR_TYPE.NO_BEFORE_MATCH:
            return '没有起始符（';
        case ERROR_TYPE.NO_AFTER_MATCH:
            return '没有结束符)';
        case ERROR_TYPE.NOT_FULL:
            return '条件不完整';
        default:
            return '其他异常';
    }
};

/**
 * 搜集树解析时的错误，始illegalResolver， errorResolver的错误
 * @param tree
 * @returns {Array}
 */
const validateBasic = tree =>
    treeReduceWithoutAfter(
        tree,
        (accumulator, node) => {
            switch (node.name) {
                case RESOLVER_NAME.ILLEGAL:
                    return addValidateResult(accumulator, {
                        nodeKey: node.$$key,
                        type: ERROR_TYPE.ILLEGAL,
                        message: '非法字符，合法字符：01234567890+-*/.@()'
                    });

                case RESOLVER_NAME.ERROR:
                    return addValidateResult(accumulator, {
                        nodeKey: node.$$key,
                        type: ERROR_TYPE.NORMAL,
                        message: getErrorMessageFromErrorType(node.errorType)
                    });

                default:
                    return accumulator;
            }
        },
        []
    );

/**
 * 搜集树简单的错误
 * @param tree
 * @returns {*}
 */
const validateSimple = tree =>
    treeReduceWithoutAfter(
        tree,
        (accumulator, node, isAfterTrigger, index, nodes) => {
            if (node.name === RESOLVER_NAME.NUMBER && node.value.length > 13) {
                return addValidateResult(accumulator, {
                    nodeKey: node.$$key,
                    type: ERROR_TYPE.LENGTH_LIMIT,
                    message: '数字的长度过长'
                });
            }

            if (node.name === RESOLVER_NAME.NUMBER && +node.value === 0 && index > 0 && nodes[index - 1].value === '/') {
                return addValidateResult(accumulator, {
                    nodeKey: node.$$key,
                    type: ERROR_TYPE.BOTTOM_ZERO,
                    message: '除数不能为0'
                });
            }

            return accumulator;
        },
        []
    );

/**
 * 四则运算规则
 * @param tree
 */
const validateArithmetic = tree =>
    treeReduceWithoutAfter(
        tree,
        (accumulator, node, isAfterTrigger, index, nodes) => {
            if (index === 0) {
                if (node.name === RESOLVER_NAME.OPERATOR && nodes.length === 1) {
                    return addValidateResult(accumulator, {
                        nodeKey: node.$$key,
                        type: ERROR_TYPE.ONLY_OPERATOR,
                        message: '单一操作符不能组成公式'
                    });
                }
                // 第1个位置出现"+"、"-"、"*"、"/"
                if (node.name === RESOLVER_NAME.OPERATOR) {
                    return addValidateResult(accumulator, {
                        nodeKey: node.$$key,
                        type: ERROR_TYPE.WRONG_POSITION,
                        message: '公式首个位置不能出现运算符："+"、"-"、"*"、"/"'
                    });
                }
            }

            if (index + 1 === nodes.length && node.name === RESOLVER_NAME.OPERATOR) {
                return addValidateResult(accumulator, {
                    nodeKey: node.$$key,
                    type: ERROR_TYPE.WRONG_POSITION,
                    message: '公式末尾不能出现运算符："+"、"-"、"*"、"/"'
                });
            }

            if (RESOLVER_NAME.GROUP === node.name && !node?.children?.length) {
                return addValidateResult(accumulator, {
                    nodeKey: node.$$key,
                    type: ERROR_TYPE.ONLY_GROUP,
                    message: '括号不能没有算式表达式'
                });
            }

            if (nodes.length <= 1 || index + 1 === nodes.length) {
                return accumulator;
            }

            const afterNode = nodes[index + 1];

            if (RESOLVER_NAME.NUMBER === node.name && afterNode.name !== RESOLVER_NAME.OPERATOR) {
                return addValidateResult(accumulator, {
                    nodeKey: afterNode.$$key,
                    type: ERROR_TYPE.WRONG_POSITION,
                    message: '数字后面只能出现运算符："+"、"-"、"*"、"/"'
                });
            }

            if (RESOLVER_NAME.CONDITION === node.name && afterNode.name !== RESOLVER_NAME.OPERATOR) {
                return addValidateResult(accumulator, {
                    nodeKey: afterNode.$$key,
                    type: ERROR_TYPE.WRONG_POSITION,
                    message: '动态条件后面只能出现运算符："+"、"-"、"*"、"/"'
                });
            }

            if (RESOLVER_NAME.GROUP === node.name && afterNode.name !== RESOLVER_NAME.OPERATOR) {
                return addValidateResult(accumulator, {
                    nodeKey: afterNode.$$key,
                    type: ERROR_TYPE.WRONG_POSITION,
                    message: '括号后面只能出现运算符："+"、"-"、"*"、"/"'
                });
            }

            if (RESOLVER_NAME.OPERATOR === node.name && afterNode.name === RESOLVER_NAME.OPERATOR) {
                return addValidateResult(accumulator, {
                    nodeKey: afterNode.$$key,
                    type: ERROR_TYPE.WRONG_POSITION,
                    message: '运算符后面不能再出现运算符："+"、"-"、"*"、"/"'
                });
            }

            return accumulator;
        },
        []
    );

/**
 * 单位运算校验
 */
const logicValidate = tree => {
    const treeUnit = calFormulaUnit(tree);

    if (treeUnit && ((treeUnit !== UNIT.CONSTANT && treeUnit !== UNIT.MONEY) || treeUnit === UNIT.ERROR)) {
        return [
            {
                type: ERROR_TYPE.UNIT_LOGICAL,
                message: '逻辑有可能存在问题，请核对仔细确认无误后再提交'
            }
        ];
    }

    return [];
};

const treeValidate = tree => {
    // 1.搜集树解析时的错误，始illegalResolver， errorResolver的错误
    const basicResult = validateBasic(tree);

    // 2.搜集树简单的错误
    const simpleResult = validateSimple(tree);

    // 3.校验四则运算规则校验
    const ruleResult = validateArithmetic(tree);

    // 4.逻辑校验
    let logicResult = [];
    try {
        logicResult = basicResult.length > 0 || simpleResult.length > 0 || ruleResult.length > 0
            ? []
            : logicValidate(tree);
    } catch (e) {
        console.error(e);
    }

    return {
        error: [...basicResult, ...simpleResult, ...ruleResult],
        warn: [...logicResult]
    };
};

export default treeValidate;
